package com.block.account.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.account.enums.AccountTypeEnum;
import com.block.account.enums.ActionTypeEnum;
import com.block.account.enums.RecordStatusEnum;
import com.block.account.service.IAccountApplyRecordService;
import com.block.account.service.IAccountItemProductService;
import com.block.account.service.IBillInfoCommonService;
import com.block.account.service.IBillInfoProductService;
import com.block.common.annotate.RedisLock;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.*;
import com.block.db.mapper.AccountItemChildMapper;
import com.block.db.mapper.BillInfoProductMapper;
import com.block.db.mapper.ProductInfoMapper;
import com.block.db.mapper.ProductProfitMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 产品账单信息表 服务实现类
 * </p>
 *
 * @author 
 * @since 2023-02-02
 */
@Service
public class BillInfoProductServiceImpl extends ServiceImpl<BillInfoProductMapper, BillInfoProduct>
        implements IBillInfoProductService, IBillInfoCommonService {

    @Resource
    ProductInfoMapper productInfoMapper;
    @Resource
    ProductProfitMapper productProfitMapper;
    @Resource
    AccountItemChildMapper accountItemChildMapper;

    @Autowired
    IAccountItemProductService accountItemProductService;
    @Autowired
    IAccountApplyRecordService accountApplyRecordService;

    /**
     * 生成产品账单
     * @param dateInfo
     * @param dataId
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public ResponseVo generatorBillInfo(String dateInfo, String dataId){

        if (StrUtil.isNotEmpty(dataId)){
            // 生成 dateInfo 的 dataId 的账单信息
            ProductProfit productProfit = productProfitMapper.findOneByDateInfoAndProductIdLock(dateInfo, Long.valueOf(dataId));
            if (ObjectUtil.isNotEmpty(productProfit)){
                this.updateProductBillInfo(productProfit);
            }
        }else{
            // 查询今日有收益的产品信息
            List<ProductProfit> productProfitList = productProfitMapper.getEntryListByDateInfo(dateInfo);
            for (ProductProfit productProfit : productProfitList) {
                this.updateProductBillInfo(productProfit);
            }
        }

        return new ResponseVo();
    }

    /**
     * 更新账单信息
     * @param productProfit
     */
    public void updateProductBillInfo(ProductProfit productProfit){

        BillInfoProduct billInfoProduct =
                this.baseMapper.getEntryByDateInfoAndDataIdLock(productProfit.getDateInfo(), String.valueOf(productProfit.getProductId()));
        if (ObjectUtil.isEmpty(billInfoProduct)){
            billInfoProduct = this.saveBillInfo(String.valueOf(productProfit.getProductId()), productProfit.getDateInfo() );
            if (ObjectUtil.isEmpty(billInfoProduct)){
                return;
            }
        }

        // 判断账单是否可以更新
        if (!ObjectUtil.equal(billInfoProduct.getStatus(), RecordStatusEnum.WAIT_CONFIRM.getValue()) &&
                !ObjectUtil.equal(billInfoProduct.getStatus(), RecordStatusEnum.UNABLE.getValue())){
            // 账单不可修改
            return;
        }

        // 查询当日消耗量

        // 查询账户余额
//        AccountItemProduct accountItemProduct =
//                accountItemProductService.getAccountInfoByProductId(String.valueOf(productProfit.getProductId()), productProfit.getProductName());

        // 查询当日充值金额
//        BigDecimal payAmount = accountItemProductService.queryPayAmount(String.valueOf(productProfit.getProductId()), productProfit.getDateInfo() );

        BillInfoProduct updateEntity = new BillInfoProduct();
        updateEntity.setId(billInfoProduct.getId());

        // 查询产品绑定的账号信息
        AccountItemChild itemChild =
                accountItemChildMapper.getEntityByDataIdAndAccountType(billInfoProduct.getProductId(), AccountTypeEnum.PROD.getValue());
        if (ObjectUtil.isNotEmpty(itemChild)){
            updateEntity.setItemAccountId(itemChild.getAccountId());
            updateEntity.setItemAccountName(itemChild.getAccountName());
            updateEntity.setStatus(RecordStatusEnum.WAIT_CONFIRM.getValue());
        }else{
            updateEntity.setStatus(RecordStatusEnum.UNABLE.getValue());
        }

        /**
         * 设置日消耗量
         */
        updateEntity.setSysNumber(productProfit.getUvNumber());
        updateEntity.setSysAmount(productProfit.getProfitAmount());
        updateEntity.setRealNumber(productProfit.getUvNumber());
        updateEntity.setRealAmount(productProfit.getProfitAmount());

        boolean updateRes = this.updateById(updateEntity);
    }

    /**
     * 新增账单信息
     * @param dataId
     * @return
     */
    public BillInfoProduct saveBillInfo(String dataId, String dateInfo){

        ProductInfo productInfo = productInfoMapper.selectById(dataId);

        BillInfoProduct billInfoProduct = new BillInfoProduct();
        billInfoProduct.setDateInfo(dateInfo);
        billInfoProduct.setProductId(String.valueOf(productInfo.getId()));
        billInfoProduct.setProductName(productInfo.getProductName());
        billInfoProduct.setPrice(productInfo.getPriceAmount());

        boolean result =  this.save(billInfoProduct);

        // 返回生成的账单信息
        return this.getById(billInfoProduct.getId());
    }




    /**
     * 产品消耗申请入账
     * @param recordId
     * @param operatorId
     * @param operatorName
     * @return
     */
    @Override
    @RedisLock(lockName = "APPLY::ENTER::BILL::PROD:", key = "#recordId")
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public ResponseVo xhApplyEnter(String recordId, String operatorId, String operatorName) {

        // 查询记录信息
        BillInfoProduct billInfoProduct = this.baseMapper.getEntryByIdLock(recordId);
        if (ObjectUtil.isEmpty(billInfoProduct)){
            return new ResponseVo(AppRspCodeConstant.DATA_INFO_NULL);
        }

        // 判断是否在操作时间
        String nowDate = LocalDate.now().toString();
        if (StrUtil.equals(nowDate, billInfoProduct.getDateInfo())){
            // 属于今日的账单
            LocalDateTime nowTime = LocalDateTime.now();
            LocalDateTime canHandleTime = LocalDateTime.now().withHour(18).withMinute(30).withSecond(0);
            if (nowTime.isBefore(canHandleTime)){
                return new ResponseVo(AppRspCodeConstant.ACTION_ERROR, "该账单不可操作", "");
            }
        }

        if (!ObjectUtil.equals(RecordStatusEnum.WAIT_CONFIRM.getValue(), billInfoProduct.getStatus())){
            return new ResponseVo(AppRspCodeConstant.PARAM_ERROR);
        }

        // 生产入账申请的信息
        AccountApplyRecord applyRecord = new AccountApplyRecord();
        applyRecord.setDateInfo(billInfoProduct.getDateInfo());

        applyRecord.setItemAccountId(billInfoProduct.getItemAccountId());
        applyRecord.setItemAccountName(billInfoProduct.getItemAccountName());
        applyRecord.setItemAccountType(AccountTypeEnum.PROD.getValue());

        applyRecord.setActionType(ActionTypeEnum.XH.getValue());

        applyRecord.setBillAmount(billInfoProduct.getRealAmount());
        applyRecord.setStatus(RecordStatusEnum.WAIT_HANDLE.getValue());

        applyRecord.setCreatorId(operatorId);
        applyRecord.setCreatorName(operatorName);

        applyRecord.setDataId(String.valueOf(billInfoProduct.getId()));
        applyRecord.setDataType(AccountTypeEnum.PROD.getValue());

        boolean save = accountApplyRecordService.save(applyRecord);
        if (!save){
            return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION);
        }

        BillInfoProduct updateEntity = new BillInfoProduct();
        updateEntity.setId(billInfoProduct.getId());
        updateEntity.setStatus(RecordStatusEnum.WAIT_HANDLE.getValue());
        boolean update = this.updateById(updateEntity);
        if (!update){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION);
        }

        return new ResponseVo(AppRspCodeConstant.SUCCESS);
    }


    /**
     * 消耗入账完成
     */
    @Override
    public boolean xhEnterSuccess(String dataId){
        BillInfoProduct updateEntity = new BillInfoProduct();
        updateEntity.setId(Long.valueOf(dataId));
        updateEntity.setStatus(RecordStatusEnum.SUCCESS.getValue());
        return this.updateById(updateEntity);
    }

}
